﻿using System;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using cludg.Infrastructure.Core.Attributes;
using nsadv.Statistic.Domain;
using nsadv.Statistic.Services;
using nsadv.Statistic.Services.Security;
using nsadv.Statistic.Web.Security;
using nsadv.Statistic.Web.ViewModels;

namespace nsadv.Statistic.Web.Controllers
{
	public class AdministrationController : BaseController
	{
		[Dependency]
		public Administration Administration { get; set; }

		[Dependency]
		public Classifier<Advertiser> AdvertiserClassifier { get; set; }

		[Dependency]
		public Classifier<Place> PlaceClassifier { get; set; }

		[RoleRequired(UserRole.Root)]
		public ActionResult Users()
		{
			var model = CreateModel<UsersModel>();
			model.NavigationMenu.SetActiveItem("UsersManagement");

			// Получить список всех пользователей от сервиса
			// TODO: Paging
			model.Users = Administration.AllUsers;

			return View(model);
		}

		[RoleRequired(UserRole.Root)]
		public ActionResult CreateUser()
		{
			var model = CreateModel<UserModel>();
			model.FillClassifiersData(AdvertiserClassifier.All, PlaceClassifier.All);

			return View("EditUser", model);
		}

		[RoleRequired(UserRole.Root)]
		[HttpPost]
		public ActionResult CreateUser(UserModel model)
		{
			InitModel(model);

			if (ModelState.IsValid)
			{
				// Проверка на существование пользовател с таким же именем
				if (Administration.AllUsers.Where(x => x.Name == model.Name).Count() > 0)
				{
					ModelState.AddModelError(string.Empty, "Пользователь с таким именем уже существует.");
					model.FillClassifiersData(AdvertiserClassifier.All, PlaceClassifier.All);
					return View("EditUser", model);
				}

				var newUser = Administration.AddUser(model.Name, model.Password);
				// Задать тип пользователя
				SetUserType(model, newUser);

				return RedirectToAction("Users");
			}

			model.FillClassifiersData(AdvertiserClassifier.All, PlaceClassifier.All);
			return View("EditUser", model);
		}

		[RoleRequired(UserRole.Root)]
		private void SetUserType(UserModel model, User user)
		{
			var userRole = (UserRole)(Enum.Parse(typeof (UserRole), model.RoleName));
			switch (userRole)
			{
				case  UserRole.None:
					Administration.MakeUserNone(user);
					break;
				case UserRole.Root:
					Administration.MakeUserRoot(user);
					break;
				case UserRole.Place:
					var place = PlaceClassifier.ById(model.PlaceId);
					if (place == null)
					{
						throw new ApplicationException(string.Format("Площадка с Id {0} не найдена.", model.PlaceId));
					}
					Administration.MakeUserPlace(user, place);
					break;
				case UserRole.Advertiser:
					var advertiser = AdvertiserClassifier.ById(model.AdvertiserId);
					if (advertiser == null)
					{
						throw new ApplicationException(string.Format("Агенство с Id {0} не найдено.", model.AdvertiserId));
					}
					Administration.MakeUserAdvertiser(user, advertiser);
					break;
				default:
					break;
			}
		}

		[RoleRequired(UserRole.Root)]
		public ActionResult EditUser(string id)
		{
			var user = Administration.AllUsers.Where(x => x.Id == id).FirstOrDefault();
			if (user == null)
			{
				ShowMessage(MessageType.Error, string.Format("Пользователь с ИД {0} не найден.", id));
				return RedirectToAction("Users");
			}

			var model = CreateModel<UserModel>();
			model.FillClassifiersData(AdvertiserClassifier.All, PlaceClassifier.All);

			model.Id = user.Id;
			model.Name = user.Name;
			model.Password = user.Password;
			model.RoleName = user.Role.ToString();
			model.AdvertiserId = user.Advertiser == null ? string.Empty : user.Advertiser.Id;
			model.PlaceId = user.Place == null ? string.Empty : user.Place.Id;

			return View("EditUser", model);
		}

		[RoleRequired(UserRole.Root)]
		[HttpPost]
		public ActionResult EditUser(UserModel model)
		{
			InitModel(model);

			if (ModelState.IsValid)
			{
				// TODO: Может методо ById?
				var user = Administration.AllUsers.Where(x => x.Id == model.Id).FirstOrDefault();
				if (user == null)
				{
					ModelState.AddModelError(string.Empty, string.Format("Пользователь с ИД {0} не найден.", model.Id));
					return View(model);
				}

				// 1. Если остался только 1 пользователь типа root и хотим изменить его тип - запретить
				int rootCount = (from usr in Administration.AllUsers where usr.Role == UserRole.Root select usr).Count();
				var userRole = (UserRole)(Enum.Parse(typeof(UserRole), model.RoleName));
				if (rootCount <= 1 && user.Role == UserRole.Root && userRole != UserRole.Root)
				{
					ShowMessage(MessageType.Warning,
						string.Format("Нельзя изменять тип пользователя типа {0}, если он остался в системе один.", user.Role));
					return RedirectToAction("Users");
				}

				user.Name = model.Name;
				user.Password = model.Password;
				Administration.UpdateUser(user);
				SetUserType(model, user);

				return RedirectToAction("Users"); 
			}

			model.FillClassifiersData(AdvertiserClassifier.All, PlaceClassifier.All);
			return View(model);
		}

		[RoleRequired(UserRole.Root)]
		public ActionResult DeleteUser(string id, string approved)
		{
			var user = Administration.AllUsers.Where(x => x.Id == id).FirstOrDefault();
			if (user == null)
			{
				ShowMessage(MessageType.Error, string.Format("Пользователь с ИД {0} не найден.", id));
				return RedirectToAction("Users");
			}
				
			if (approved == "y")
			{
				// Проверки
				// 1. Нельзя удалять текущего пользователя
				if (GetCurrentUserId() == user.Id)
				{
					ShowMessage(MessageType.Warning, "Нельзя удалять пользователя, под которым Вы вошли в систему.");
					return RedirectToAction("Users");
				}
				// 2. Если остался только 1 пользователь типа root и хотим его удалить - запретить
				int rootCount = (from usr in Administration.AllUsers where usr.Role == UserRole.Root select usr).Count();
				if (rootCount <= 1 && user.Role == UserRole.Root)
				{
					ShowMessage(MessageType.Warning, 
						string.Format("Нельзя удалять пользователя типа {0}, если он остался в системе один.", user.Role));
					return RedirectToAction("Users");
				}

				Administration.DeleteUser(user);
				return  RedirectToAction("Users");
			}

			var model = new ConfirmationModel(string.Format("Удалить пользователя '{0}'?", user.Name),
				                                UrlHelper.GenerateUrl(null, "DeleteUser", "Administration",
				                                                    new RouteValueDictionary {{"id", id}, {"approved", "y"}},
				                                                    RouteTable.Routes, Request.RequestContext, true),
				                                UrlHelper.GenerateUrl(null, "Users", "Administration", null, RouteTable.Routes,
				                                                    Request.RequestContext, true));
			InitModel(model);
			return View("Confirm", model);
		}
	}
}
